package com.util;

import java.io.PrintStream;
import org.apache.commons.logging.Log;

// Referenced classes of package com.util:
//            Logger, Config

public final class Clock extends Thread
{

    public static synchronized long clock()
    {
        return _clock;
    }

    public static void setUnsynchTicks(int ticks)
    {
        if(ticks <= 0)
            ticks = 100;
        else
        if(ticks < 100)
            ticks = 100;
        _unsynchTicks = ticks;
    }

    public static int getUnsynchTicks()
    {
        return _unsynchTicks;
    }

    public static void setSynchEvery(int every)
    {
        if(every <= 0)
            every = 10;
        _synchEvery = every;
    }

    public static synchronized void advance(long byMillis)
    {
        _advance += byMillis;
        _clock += byMillis;
    }

    public static long getAdvance()
    {
        return _advance;
    }

    public void run()
    {
        do
            try
            {
                for(int i = 0; i < _synchEvery; i++)
                {
                    sleep(_unsynchTicks);
                    synchronized(com.util.Clock.class)
                    {
                        _clock += _unsynchTicks + _adjust;
                    }
                }

                synchronize();
            }
            catch(Throwable thrw)
            {
                log.error("Internal error in clock daemon", thrw);
            }
        while(true);
    }

    public static synchronized long synchronize()
    {
        long current = System.currentTimeMillis();
        long clock = _clock;
        long retarded = clock - _advance;
        if(current != retarded)
        {
            int adjust = (int)(current - retarded) / _synchEvery;
            if(adjust != 0)
                _adjust += adjust;
        }
        if(current > retarded)
        {
            clock = current + _advance;
            _clock = clock;
        }
        return clock;
    }

    private Clock()
    {
        super("com.eway.util.clockDaemon");
        _clock = System.currentTimeMillis();
        setPriority(10);
        setDaemon(true);
        start();
    }

    public static void main(String args[])
    {
        try
        {
            int count = 0xf4240;
            //System.out.println("Using Clock.clock()");
            long clock = System.currentTimeMillis();
            for(int i = 0; i < count; i++)
                if(i % 100 == 0)
                    synchronize();
                else
                    clock();

            clock = System.currentTimeMillis() - clock;
            //System.out.println("Performed " + count + " in " + clock + "ms");
            //System.out.println("Using System.currentTimeMillis()");
            clock = System.currentTimeMillis();
            for(int i = 0; i < count; i++)
                System.currentTimeMillis();

            clock = System.currentTimeMillis() - clock;
            //System.out.println("Performed " + count + " in " + clock + "ms");
        }
        catch(Exception except) { }
    }

    private static Log log;
    public static final int UNSYNCH_TICKS = 100;
    public static final int SYNCH_EVERY = 10;
    private static long _clock;
    private static int _unsynchTicks;
    private static int _synchEvery;
    private static long _advance;
    private static int _adjust;
    //public static final String PROPERTY_UNSYNCH_TICKS = "UUID.clock.unsynchTicks";
    //public static final String PROPERTY_SYNCH_EVERY = "UUID.clock.synchEvery";

    static
    {
        int value = 100;
        _unsynchTicks = value <= 0 ? 100 : value;
        value = 10;
        _synchEvery = value <= 0 ? 10 : value;
        new Clock();
    }
}
